﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using Framework.Common.Reflection;
using Framework.Common.Reflection.RunSharpEmit;
using Framework.Common;
namespace System
{
    public static class DataReaderExtension
    {
        public static T ToModel<T>(this IDataReader dr) where T : new()
        {
            var func = GetFuncDataReaderToEntity<T>();
            using (dr)
            {
                while (dr.Read())
                {
                    T model = func(dr);
                    return model;
                }
            }
            return default(T);
        }

        public static IList<T> ToList<T>(this IDataReader dr) where T : new()
        {
            IList<T> list = new List<T>();
            var func = GetFuncDataReaderToEntity<T>();
            using (dr)
            {
                while (dr.Read())
                {
                    list.Add(func(dr));
                }
            }
            return list;
        }


        private static Func<IDataRecord, T> GetFuncDataReaderToEntity<T>() where T : new()
        {
            return DynamicMethodCreate.CreateFunc<IDataRecord, T>(cg =>
                {
                    var pis = typeof(T).GetProperties();
                    if (pis != null && pis.Length > 0)
                    {
                        var model = cg.Local(Exp.New(typeof(T)));
                        foreach (var pi in pis)
                        {
                            if (DynamicMethodCreate.ObjectConvertMethodDict.ContainsKey(pi.PropertyType))
                            {
                                string convertMethodName = DynamicMethodCreate.ObjectConvertMethodDict[pi.PropertyType];
                                Operand orignal = cg.Local(cg.Arg("p0")[pi.Name]);
                                cg.If(orignal.NE(null));
                                Operand value = Static.Invoke(typeof(TypeConvertHelper), convertMethodName, cg.Arg("p0")[pi.Name]);
                                cg.Assign(model.Property(pi.Name), value);
                                cg.End();
                            }
                        }
                        cg.Return(model);
                    }
                    else
                    {
                        throw new Exception(typeof(T).Name + " not contains any property");
                    }

                }, "GetFuncDataReaderToEntity" + typeof(T).GetHashCode());
        }

    }


}
